ARM指令之精髓DMB,DSB,ISB指令 您所在的位置:网站首页 arm dmb 指令 ARM指令之精髓DMB,DSB,ISB指令

ARM指令之精髓DMB,DSB,ISB指令

2024-07-01 11:22| 来源: 网络整理| 查看: 265

4.3.5 汇编语言:指令隔离(barrier)指令和存储器隔离指令

CM3 中的另一股新鲜空气是一系列的隔离指令。它们在一些结构比较复杂的存储器系统中是需要的(典型地用于流水线和写缓冲——译者注)。在这类系统中,如果没有必要的隔离,会导致系统发生紊乱危象,(相当于数电中的“竞争 与冒险”——译者注).

举例来说,如果可以在运行时更改存储器的映射关系或者内存保护区的设置,(通过写 MPU 的寄存 器),就必须在更改之后立即补上一条 DSB 指令(数据同步指令)。因为对 MPU 的写操作很可能会被放到一个写缓冲中。写缓冲是为了提高存储器的总体访问效率而设的,但它也有副作用,其中之一,就是会导致写内存的指令被延迟几个周期执行,因此对存储器的设置不能即刻生效,这会导致紧临着的下一 条指令仍然使用旧的存储器设置——但程序员的本意显然是使用新的存储器设置。这种紊乱危象是后患无穷的,常会破坏未知地址的数据,有时也会产生非法地址访问。CM3 提供隔离指令族,就是要消灭这些紊乱危象。

(这些汇编指令都是不带参数的,以下指令只适用于使用Cortex-M0作为内核的芯片,使用其他架构的芯片不一定适用,需要查询其参考手册确定)

CPSIE I 清除PRIMASK(使能中断);在符合CMSIS的设备驱动库中,可以使用“__enable_irq()”实现该操作 CPSID I 设置PRIMASK(禁止中断);在符合CMSIS的设备驱动库中,可以使用“__disable_irq()”实现该操作 DMB 数据存储器屏障,确保在新的存储器访问开始之前,所有的存储器访问已经完成。在符合CMSIS的设备驱动库中,可以使用“__DMB”函数实现该操作 DSB 数据同步屏障,确保在下一条指令开始执行前,所有的存储器访问已经完成。在符合CMSIS的设备驱动库中,可以使用“__DSB”函数实现该操作 ISB 指令同步屏障,清除流水线并且确保在新指令执行时,之前的指令都已经执行完毕。在符合CMSIS的设备驱动库中,可以使用“__ISB”函数实现该操作 NOP 无操作。在符合CMSIS的设备驱动库中,可以使用“__NOP()”实现该操作 SEV 多处理器环境中向所有的处理器发送事件(包括自身)。在符合CMSIS的设备驱动库中,可以使用“__SEV()”实现该操作 WFE 等待事件,如果没有之前该事件的记录,进入休眠模式;如果有的话,则清除事件锁存并继续执行;在符合CMSIS的设备驱动库中,可以使用“__WFE()”函数实现该操作,不过若你使用供应商特定的休眠模式,效果会更好 WFI 等待中断,进入休眠模式。在符合CMSIS的设备驱动库中,可以使用“__WFI()”实现该操作,不过若你使用供应商特定的休眠模式,效果会更好 YIELD 用于线程切换,表明任务被延迟了,在Cortex-M0上效果和NOP一样

DMB 在双口 RAM 以及多核架构的操作中很有用。如果 RAM 的访问是带缓冲的,并且写完之后马上读,就必须让它“喘口气”——用 DMB 指令来隔离,以保证缓冲中的数据已经落实到 RAM 中。 DSB 比 DMB 更保险(当然也是有执行代价的),它是宁可错杀也不漏网——清空了写缓冲,使得任何它后面的指令,不管要不要使用先前的存储器访问结果,通通等待访问完成。大虾们可以在有绝对信心时使用 DMB,新手还是使用 DSB 比较保险。

同 DMB/DSB 相比,ISB 指令看起来似乎最强悍,但是却一身都是“愣劲”,不由分说就“动粗”。不过它还有其它的用场——对于高级底层技巧:“自我更新”代码,非常有用。举例来说,如果某个程序从下一条要执行的指令处更新了自己,但是先前的旧指令已经被预取到流水线中去了,此时就必须清洗流水线,把旧版本的指令洗出去,再预取新版本的指令。因此,必须在被更新代码段的前面使用 ISB,以保证旧的代码从流水线中被清洗出去,不再有机会执行。

这些汇编指令初学者也许不会用到,一般我们都用符合CMSIS设备驱动库编程,读者可以在core_cminstr.h文件中中找到这些指令的声明和定义。部分源码如下:

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455/** \brief  No Operation     No Operation does nothing. This instruction can be used for code alignment purposes.  */ #define __NOP                             __nop     /** \brief  Wait For Interrupt     Wait For Interrupt is a hint instruction that suspends execution     until one of a number of events occurs.  */ #define __WFI                             __wfi     /** \brief  Wait For Event     Wait For Event is a hint instruction that permits the processor to enter     a low-power state until one of a number of events occurs.  */ #define __WFE                             __wfe     /** \brief  Send Event     Send Event is a hint instruction. It causes an event to be signaled to the CPU.  */ #define __SEV                             __sev     /** \brief  Instruction Synchronization Barrier     Instruction Synchronization Barrier flushes the pipeline     in the processor, so that all instructions following the ISB     are fetched from cache or  memory, after the instruction     has been completed.  */ #define __ISB()                           __isb(0xF)     /** \brief  Data Synchronization Barrier     This function acts as a special kind of Data Memory Barrier.     It completes when all explicit memory accesses before     this instruction complete.  */ #define __DSB()                           __dsb(0xF)   /** \brief  Data Memory Barrier     This function ensures the apparent order of the explicit memory     operations before and after the instruction,     without ensuring their completion.  */ #define __DMB()                           __dmb(0xF)     /** \brief  Reverse byte order (32 bit)     This function reverses the byte order in integer value.     \param [in] value Value to reverse     \return Reversed value  */


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有